package com.jinlia.show.modules.wxapp.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.jinlia.show.common.core.exception.MyRuntimeException;
import com.jinlia.show.common.core.utils.JavaJwtUtils;
import com.jinlia.show.common.core.utils.UserInfoUtils;
import com.jinlia.show.modules.base.system.entity.MemberCard;
import com.jinlia.show.modules.base.system.service.MemberCardMapperService;
import com.jinlia.show.modules.base.wxapp.entity.AccessToken;
import com.jinlia.show.modules.base.wxapp.entity.AppConfig;
import com.jinlia.show.modules.base.wxapp.entity.User;
import com.jinlia.show.modules.base.wxapp.entity.UserRole;
import com.jinlia.show.modules.base.model.po.UserPO;
import com.jinlia.show.modules.base.wxapp.service.AppConfigMapperService;
import com.jinlia.show.modules.base.wxapp.service.UserMapperService;
import com.jinlia.show.modules.base.wxapp.service.UserRoleMapperService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class UserService {
    private Logger logger = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private UserMapperService userMapperService;
    @Autowired
    private AccessTokenService accessTokenService;
    @Autowired
    private UserRoleMapperService userRoleMapperService;
    @Autowired
    private MemberCardMapperService memberCardMapperService;
    @Autowired
    private AppConfigMapperService appConfigMapperService;

    @Autowired
    private RestTemplate restTemplate;

    public String codeToSession = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
    public String getUserPhoneNumber = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";


    public UserPO login(String jsCode, String appId) {
        AppConfig appConfig = appConfigMapperService.lambdaQuery().eq(AppConfig::getAppId, appId).one();
        /**
         * 微信登录
         */
        ResponseEntity<String> getCodeResponse = restTemplate.getForEntity(String.format(codeToSession, appId, appConfig.getAppSecret(), jsCode), String.class);
        JSONObject jsonCodeResponse = null;
        if (HttpStatus.OK.equals(getCodeResponse.getStatusCode())) {
            logger.info("微信调用成功={}", getCodeResponse.getBody());
            jsonCodeResponse = JSONObject.parseObject(getCodeResponse.getBody());
            if (Objects.isNull(jsonCodeResponse.getString("openid"))) {
                throw new MyRuntimeException("微信获取code失败");
            }
        } else {
            throw new MyRuntimeException("调用微信登录aip失败");
        }
        User user = userMapperService.lambdaQuery().eq(User::getOpenid, jsonCodeResponse.getString("openid")).one();
        if (user == null) {//保存
            user = new User();
            user.setNickName("游客");
            user.setOpenid(jsonCodeResponse.getString("openid"));
            user.setCreateTime(LocalDateTime.now());
            user.setLastLoginTime(LocalDateTime.now());
            userMapperService.save(user);
        } else {//更新
            userMapperService.lambdaUpdate()
                    .set(User::getLastLoginTime, LocalDateTime.now())
                    .eq(User::getId, user.getId())
                    .update();
        }
        JWTCreator.Builder builder = JWT.create();
        // 构建token
        builder.withClaim("userId", user.getId());
        builder.withClaim("userName", user.getNickName());
        builder.withClaim("appId", appId);
        builder.withClaim("openid", user.getOpenid());
        String token = builder.sign(Algorithm.HMAC256(JavaJwtUtils.SECRET));
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setHeader("authorization", token);
        UserPO userPO = UserPO.fromEntity(user);
        //填充角色
        List<UserRole> list = userRoleMapperService.lambdaQuery()
                .eq(UserRole::getUserId, user.getId())
                .list();
        userPO.setUserRoles(list);
        //填充会员信息
        if (Objects.nonNull(userPO.getMemberCardId())) {
            MemberCard byIdMemberCard = memberCardMapperService.getById(userPO.getMemberCardId());
            userPO.setMemberCard(byIdMemberCard);
        }
        return UserPO.fromEntity(userPO);
    }

    public UserPO getUserPhoneNumber(String code) {
        //获取token
        AccessToken accessToken = accessTokenService.getAccessToken();
        JSONObject param = new JSONObject();
        param.put("code", code);
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(String.format(getUserPhoneNumber, accessToken.getAccessToken()),
                param, String.class);
        logger.info("获取微信手机号={}", stringResponseEntity.getBody());
        if (!HttpStatus.OK.equals(stringResponseEntity.getStatusCode())) {
            throw new MyRuntimeException("5002", "调用微信登录aip失败");
        }
        JSONObject jsonObject = JSONObject.parseObject(stringResponseEntity.getBody());
        if (!"0".equals(jsonObject.getString("errcode"))) {
            throw new MyRuntimeException("5002", "微信获取手机号失败");
        }
        //手机号
        String phoneNumber = jsonObject.getJSONObject("phone_info").getString("phoneNumber");
        userMapperService.lambdaUpdate()
                .set(User::getPhoneNumber, phoneNumber)
                .eq(User::getId, UserInfoUtils.getUserId())
                .update();
        User user = userMapperService.getById(UserInfoUtils.getUserId());
        return UserPO.fromEntity(user);
    }

    /**
     * 更新用户信息
     *
     * @param user
     * @return
     */
    public User updateById(User user) {
        logger.info("修改用户信息::", JSON.toJSONString(user));
        userMapperService.lambdaUpdate()
                .set(StringUtils.hasLength(user.getAvatarUrl()), User::getAvatarUrl, user.getAvatarUrl())
                .set(StringUtils.hasLength(user.getNickName()), User::getNickName, user.getNickName())
                .set(StringUtils.hasLength(user.getPhoneNumber()), User::getPhoneNumber, user.getPhoneNumber())
                .set(User::getLastUpdateTime, LocalDateTime.now())
                .eq(User::getId, UserInfoUtils.getUserId())
                .update();
        User one = userMapperService.getById(UserInfoUtils.getUserId());
        return one;
    }
}
